﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Castle.Windsor;
using Microsoft.Win32;
using SuppKids.Controls;
using SuppKids.Converters;
using SuppKids.Core;
using SuppKids.Core.Domain;
using SuppKids.Core.Extensions;
using SuppKids.Core.Reporting;
using SuppKids.Core.Reporting.Data;
using SuppKids.Core.Services;
using SuppKids.Resources;
using SuppKids.ViewModels;
using SuppKids.ViewModels.MenuRaskladka;


namespace SuppKids
{
	/// <summary>
	/// Interaction logic for MenuRaskladka.xaml
	/// </summary>
	public partial class MenuRaskladka : BaseWindow
	{
		private readonly DailyMenuService dailyMenuService;
		private readonly ProductService productService;
        private readonly GroupService groupService;
		private readonly ReportGeneratorFactory reportGeneratorFactory;
		public GroupsViewModel[] Groups { get; set; }
		public DailyMenu SelectedDailyMenu { get; set; }

		public MenuRaskladka(IWindsorContainer container, LicenseService licenseService,
                DailyMenuService dailyMenuService, ProductService productService, 
                ReportGeneratorFactory reportGeneratorFactory, GroupService groupService)
			: base(container, licenseService)
		{
			this.dailyMenuService = dailyMenuService;
			this.productService = productService;
			this.reportGeneratorFactory = reportGeneratorFactory;
            this.groupService = groupService;
			this.Groups = groupService.GetAll().Select(a => new GroupsViewModel(a)).ToArray();
			InitializeComponent();

			this.ChildrenGroups.ItemsSource = this.Groups;
			this.BindChildrenCountGrid();
			this.Filter.OnFilterChanged += OnFilterChanged;

            int row = 2;
            foreach (Group group in AllGroups) {
                CheckBox cbx = new CheckBox();
                cbx.Content = group.Name;
                cbx.IsChecked = true;
                cbx.Name = "group_" + group.Id.ToString();
                cbx.Margin = new Thickness( 10, 0, 0, 0) ;
                RowDefinition rowDef = new RowDefinition();
                this.ParentsReportGroupsGrid.RowDefinitions.Add(rowDef);
                this.ParentsReportGroupsGrid.Children.Add(cbx);
                Grid.SetColumn(cbx, 0);
                Grid.SetRow(cbx, row);
                row++;
            }
		}
        public IEnumerable<Group> AllGroups
        {
            get
            {
                var items = this.groupService.GetAll();
                return items;
            }
        }
		private void OnFilterChanged(object sender, Filter.FilterEventArgs e)
		{
            try
            {
                this.SelectedDailyMenu = this.dailyMenuService.GetDailyMenu(e.FilterData.DayOfWeek, e.FilterData.WeekNumber, e.FilterData.MenuType, e.FilterData.MealType);

                if (this.SelectedDailyMenu != null)
                {
                    this.DishesList.ItemsSource = SelectedDailyMenu.Dishes;

                    var fef = new FrameworkElementFactory(typeof(TextBlock));
                    fef.SetBinding(TextBlock.TextProperty, new Binding { Converter = new DishDisplayConverter(), ConverterParameter = this.SelectedDailyMenu });

                    this.DishesList.ItemTemplate = new DataTemplate { VisualTree = fef };
                }

                this.UpdateResultGrid();
            }
            catch { }
		}

		private void UpdateResultGrid()
		{
			if (this.Filter.FilterData == null)
			{
				return;
			}

			var dailyMenus = this.dailyMenuService.GetAll(this.Filter.FilterData.DayOfWeek, this.Filter.FilterData.WeekNumber, this.Filter.FilterData.MenuType).ToArray();

			var result = new List<ResultListItem>();
			foreach (var dailyMenu in dailyMenus)
			{
				var dishes = dailyMenu.Dishes.ToArray();
				foreach (var dish in dishes)
				{
					var ingredients = dish.Ingredients.ToArray();
					foreach (var ingredient in ingredients)
					{
						var item = new ResultListItem
						{
							DishName = dish.Name,
							MealType = dailyMenu.MealType,
							ProductName = ingredient.Product.Name,
							ConsumptionValues = ingredient.ConsumptionValues.Where(a => a.DailyMenu.Id == dailyMenu.Id).ToArray(),
							Cipher = ingredient.Product.Cipher,
							Price = ingredient.Product.Price
						};
						result.Add(item);
					}
				}
			}

			this.ResultGrid.Columns.Clear();
			this.ResultGrid.Columns.Add(new DataGridTextColumn { Header = Labels.TableHeader_MealType, Binding = new Binding(Lambda.Property<ResultListItem>(a => a.MealType)) { Converter = new EnumToLocalizedValueConverter() } });
			this.ResultGrid.Columns.Add(new DataGridTextColumn { Header = Labels.TableHeader_DishName, Binding = new Binding(Lambda.Property<ResultListItem>(a => a.DishName)) });
			this.ResultGrid.Columns.Add(new DataGridTextColumn { Header = Labels.TableHeader_ProductName, Binding = new Binding(Lambda.Property<ResultListItem>(a => a.ProductName)) });

			foreach (var group in this.Groups)
			{
				if (group.IsUsed)
				{
					this.ResultGrid.Columns.Add(new DataGridTextColumn
					{
						Header = string.Format(Labels.TableHeader_ConsumptionGroup, group.GroupName),
						Binding =
							new Binding
							{
								Converter = new ResultListItemConverter(),
								ConverterParameter = new object[] { group.GroupId, dailyMenus }
							}
					});
				}
			}

			foreach (var group in this.Groups)
			{
				if (group.IsUsed)
				{
					this.ResultGrid.Columns.Add(new DataGridTextColumn
					{
						Header = string.Format(Labels.TableHeader_ChildrenCountFormat, group.GroupName),
						Binding =
							new Binding()
							{
								Converter = new ResultListItemToChildrenCountConverter(),
								ConverterParameter = group
							}
					});
				}
			}


			this.ResultGrid.Columns.Add(new DataGridTextColumn { Header = Labels.TableHeader_Price, Binding = new Binding(Lambda.Property<ResultListItem>(a => a.Price)) });
			this.ResultGrid.Columns.Add(new DataGridTextColumn { Header = Labels.TableHeader_Cipher, Binding = new Binding(Lambda.Property<ResultListItem>(a => a.Cipher)) });

			this.ResultGrid.ItemsSource = result.OrderBy(a => a.MealType);
		}

		private void SetChildrenCountButton_Click(object sender, RoutedEventArgs e)
		{
			this.ChildrenCountSelection.Visibility = Visibility.Visible;
		}

		private void BindChildrenCountGrid()
		{
			var mealTypes = Enum.GetValues(typeof(MealType)).Cast<MealType>();

			this.ChildrenGroups.Columns.Clear();
			this.ChildrenGroups.Columns.Add(new DataGridTextColumn
			{
				Header = Labels.TableHeader_Group,
				Binding = new Binding(Lambda.Property<GroupsViewModel>(a => a.GroupName)),
				IsReadOnly = true,
				Width = 100
			});

			foreach (var mealType in mealTypes)
			{
				var column = new DataGridTextColumn
				{
					Header = mealType.GetLocalizedEnumValue(),
					Binding = new Binding(Lambda.Property<GroupsViewModel>(a => a.ChildrenCount) + "[" + (int)mealType + "]"),
					MinWidth = ActualWidth,
					Width = new DataGridLength(1, DataGridLengthUnitType.Star)
				};

				this.ChildrenGroups.Columns.Add(column);
			}

		}

		private void SaveChildrenCountButton_Click(object sender, RoutedEventArgs e)
		{
			this.ChildrenCountSelection.Visibility = Visibility.Collapsed;
			this.UpdateResultGrid();
		}

		private void MainReportButtonClick(object sender, RoutedEventArgs e)
		{
			if (this.SelectedDailyMenu == null)
			{
				MessageBox.Show(Messages.DailyMenuIsNotSelected);
				return;
			}

			var saveFile = new SaveFileDialog
			{
				FileName = "Меню-требование.xlsx",
				DefaultExt = ".xlsx",
				Filter = "Excel files (.xlsx)|*.xlsx"
			};

			if (saveFile.ShowDialog() == true)
			{
				Stream stream = null;
				try
				{
					stream = saveFile.OpenFile();
					var reportGenerator = this.reportGeneratorFactory.GetReportGenerator(ReportType.MenuRequirement, ReportFormat.Excel);

					var dailyMenus = this.dailyMenuService.GetAll(this.Filter.FilterData.DayOfWeek, this.Filter.FilterData.WeekNumber, this.Filter.FilterData.MenuType).ToArray();
					var allProducts = this.productService.GetAll();
					var allGroups = this.Groups.Where(a => a.ChildrenCount.Any(b => b.Value > 0)).Select(a => new GroupData(a.Group, a.ChildrenCount));
					var reportData = new MenuRequirementReportData(
						dailyMenus,
						allProducts,
						allGroups);
					reportGenerator.GenerateReport(reportData, stream);
				}
				catch (Exception)
				{
					MessageBox.Show(Messages.SaveFileError);
				}
				finally
				{
					if (stream != null)
					{
						stream.Dispose();
					}
				}
			}
		}

        private void ParentsReportButtonClick(object sender, RoutedEventArgs e)
        {
            this.GroupsSelection.Visibility = Visibility.Visible;
        }

        private void SaveParentsMenuButton_Click(object sender, RoutedEventArgs e)
		{
			if (this.SelectedDailyMenu == null)
			{
				MessageBox.Show(Messages.DailyMenuIsNotSelected);
				return;
			}

			var saveFile = new SaveFileDialog
			{
				FileName = "Меню для родителей.xlsx",
				DefaultExt = ".xlsx",
				Filter = "Excel files (.xlsx)|*.xlsx"
			};

			if (saveFile.ShowDialog() == true)
			{
				Stream stream = null;
                try
                { 
                    var inq = new int[AllGroups.Count()];
                    int index = 2;
                    foreach (Group group in AllGroups)
                    {
                        CheckBox cbx = (CheckBox)this.ParentsReportGroupsGrid.Children[index];
                        if ((bool)cbx.IsChecked)
                            inq[index - 2] = int.Parse(cbx.Name.Replace("group_", ""));
                        else
                            inq[index - 2] = 0;
                        index++;
                    }
                  
					stream = saveFile.OpenFile();
					var reportGenerator = this.reportGeneratorFactory.GetReportGenerator(ReportType.Parents, ReportFormat.Excel);
					var dailyMenus = this.dailyMenuService.GetAll(this.Filter.FilterData.DayOfWeek, this.Filter.FilterData.WeekNumber, this.Filter.FilterData.MenuType).ToArray();
					//var allGroups = this.Groups.Select(a => new GroupData(a.Group, a.ChildrenCount)).Where(a => a.Group.Id.("1","2") );
                    //groupService.GetAll().Select(a => new GroupsViewModel(a)).ToArray();                
                    
                    //var allGroups = this.groupService.GetAll(a => inq.Contains(a.Id)).Select(a => new GroupsViewModel(a)).
                            //ToArray().Select(a => new GroupData(a.Group, a.ChildrenCount));//.Where(a => a.Group.Id.("1","2") );
                    var allGroups = this.Groups.Where(a => a.ChildrenCount.Any(b => b.Value > 0)).Select(a => new GroupData(a.Group, a.ChildrenCount));
					reportGenerator.GenerateReport(new ParentsReportData(dailyMenus, this.Filter.FilterData.DayOfWeek, this.Filter.FilterData.WeekNumber, this.Filter.FilterData.MenuType, allGroups), stream);
				}
				catch (Exception)
				{
					MessageBox.Show(Messages.SaveFileError);
				}
				finally
				{
					if (stream != null)
					{
						stream.Dispose();
					}
				}
			}
            this.GroupsSelection.Visibility = Visibility.Collapsed;
		}

        private void ReturnReportButtonClick(object sender, RoutedEventArgs e)
        {
			var saveFile = new SaveFileDialog
			{
                FileName = "Возврат продуктов.xlsx",
                DefaultExt = ".xlsx",
                Filter = "Excel files (.xlsx)|*.xlsx"
			};

            if (saveFile.ShowDialog() == true)
            {
                Stream stream = null;
                try
                {
                    stream = saveFile.OpenFile();
                    var reportGenerator = this.reportGeneratorFactory.GetReportGenerator(ReportType.ReturnProduct, ReportFormat.Excel);
                    reportGenerator.GenerateReport(null, stream);
                }
                catch (Exception)
                {
                    MessageBox.Show(Messages.SaveFileError);
                }
                finally
                {
                    if (stream != null)
                    {
                        stream.Dispose();
                    }
                }
            }

        }

        private void CancelParentsMenuButton_Click(object sender, RoutedEventArgs e)
        {
            this.GroupsSelection.Visibility = Visibility.Collapsed;
        }

        private void CancelChildrenCountButton_Click(object sender, RoutedEventArgs e)
        {
            this.ChildrenCountSelection.Visibility = Visibility.Collapsed;
        }

        private void SelectAllgroupsForParents(object sender, RoutedEventArgs e)
        {
            bool? allChecked = this.CheckAllGroups.IsChecked;
            int index = 2;
            foreach (Group group in AllGroups)
            {
                CheckBox cbx = (CheckBox)this.ParentsReportGroupsGrid.Children[index];
                cbx.IsChecked = allChecked;
                index++;
            }
        }
	}
}
